package com.linln.core.utils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;

public class DateUtils {

    public static final Timestamp ZERO_TIMESTAMP  = new Timestamp(0);
    public static final String    FORMAT_DATE     = "yyyy-MM-dd";
    public static final String    FORMAT_DATETIME = "yyyy-MM-dd HH:mm:ss";

    public static Date str2Date(String str, String pattern) {
        Date date = null;
        DateFormat format;
        try {
            if (str == null || str.trim().equals("")) {
                return null;
            }
            if (str.length() < pattern.length()) {
                pattern = pattern.substring(0, str.length());
            } else if (str.length() > pattern.length()) {
                str = str.substring(0, pattern.length());
            }
            format = new SimpleDateFormat(pattern, Locale.CHINESE);
            date = format.parse(str);
        } catch (Exception e) {
            try {
                format = new SimpleDateFormat(pattern, Locale.ENGLISH);
                date = format.parse(str);
            } catch (Exception e2) {
            }
        }
        return date;
    }

    public static Date str2Date(String str) {
        return str2Date(str, FORMAT_DATE);
    }

    public static Date str2DateTime(String str) {
        return str2Date(str, FORMAT_DATETIME);
    }

    public static Date str2DateTime(String str, Date defaultDate) {
        if (StringUtils.isBlank(str)) {
            return defaultDate;
        }
        return str2Date(str, FORMAT_DATETIME);
    }

    public static Timestamp str2Timestamp(String str) {
        Timestamp rs = null;
        try {
            rs = Timestamp.valueOf(str);
        } catch (Exception e) {
            Date date = str2Date(str);
            if (date != null) {
                rs = new Timestamp(date.getTime());
            }
        }
        return rs;
    }

    public static Timestamp toTimestamp(Date date) {
        return new Timestamp(date.getTime());
    }

    public static String date2Str(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        String str = null;
        try {
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            str = format.format(date);
            format = null;
        } catch (Exception e) {
        }
        return str;
    }

    public static String date2Str2(Date dt) {
        String tmstr = String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", dt);
        return tmstr;
    }

    public static String date2Str(Date date) {
        return date2Str(date, FORMAT_DATE);
    }

    public static String datetime2Str(Date date) {
        return date2Str(date, FORMAT_DATETIME);
    }

    public static Timestamp now() {
        return new Timestamp(System.currentTimeMillis());
    }

    public static Timestamp nowDay() {
        return toTimestamp(today());
    }

    public static Date today() {
        return formatDate(new Date(), FORMAT_DATE);
    }

    public static Date lastSecond() {
        return lastSecond(today());
    }

    public static Date lastSecond(Date date) {
        return add(date, 0, 0, 1, 0, 0, -1);
    }

    public static Date formatDate(Date date) {
        return formatDate(date, FORMAT_DATE);
    }

    public static Timestamp formatDate(Timestamp date) {
        return toTimestamp(formatDate(date, FORMAT_DATE));
    }

    public static Date formatDatetime(Date date) {
        return formatDate(date, FORMAT_DATETIME);
    }

    public static Date formatDate(Date date, String pattern) {
        try {
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            return format.parse(format.format(date));
        } catch (ParseException e) {
        }
        return null;
    }

    public static Date add(Date date, TimeUnit unit, long amount) {
        try {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.MILLISECOND, (int) unit.toMillis(amount));
            return c.getTime();
        } catch (Exception e) {
        }
        return null;
    }

    public static Date add(Date date, int field, int amount) {
        try {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(field, amount);
            return c.getTime();
        } catch (Exception e) {
        }
        return null;
    }

    public static Date add(Date date, int year, int month, int day, int hour, int minute, int second) {
        try {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.YEAR, year);
            c.add(Calendar.MONTH, month);
            c.add(Calendar.DATE, day);
            c.add(Calendar.HOUR, hour);
            c.add(Calendar.MINUTE, minute);
            c.add(Calendar.SECOND, second);
            return c.getTime();
        } catch (Exception e) {
        }
        return null;
    }

    public static Timestamp add(Timestamp date, int field, int amount) {
        try {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(field, amount);
            return new Timestamp(c.getTimeInMillis());
        } catch (Exception e) {
        }
        return null;
    }

    public static Date addYear(Date date, int amount) {
        return add(date, Calendar.YEAR, amount);
    }

    public static Date addMonth(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    public static Date addDays(Date date, int amount) {
        return addDay(date, amount);
    }

    public static Date addDay(Date date, int amount) {
        return add(date, Calendar.DATE, amount);
    }

    public static Date addWeek(Date date, int amount) {
        return add(date, Calendar.WEEK_OF_YEAR, amount);
    }

    public static Date addHour(Date date, int amount) {
        return add(date, Calendar.HOUR, amount);
    }

    public static Date addSecond(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    public static Date getYearHead(Date date) {
        return formatDate(date, "yyyy");
    }

    public static Date getMonthHead(Date date) {
        return formatDate(date, "yyyy-MM");
    }

    public static Date getWeekMonday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_YEAR, -1); // 解决周日会出现 并到下一周的情况
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTime();
    }

    public static Date getMonthTail(Date date, String pattern) {
        return formatDate(addSecond(addMonth(getMonthHead(date), 1), -1), pattern);
    }

    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return false;
        }
        return date2Str(date1).equals(date2Str(date2));
    }

    /**
     * date1 - date2的时间差
     */
    public static long getTimeDiff(Date date1, Date date2, TimeUnit unit) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("date1:" + date1 + ", date2:" + date2 + " both cannot be null!!");
        }
        return unit.convert(date1.getTime() - date2.getTime(), TimeUnit.MILLISECONDS);
    }

    public static long getTimeDiff(Timestamp date1, Timestamp date2, TimeUnit unit) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("date1:" + date1 + ", date2:" + date2 + " both cannot be null!!");
        }
        return unit.convert(date1.getTime() - date2.getTime(), TimeUnit.MILLISECONDS);
    }

    public static Date addMinute(Date startTime, int i) {
        return add(startTime, Calendar.MINUTE, i);
    }

    public static String millis2str(long t) {
        return DateUtils.datetime2Str(new Date(t));
    }

    /**
     * @param active_time_
     */
    public static boolean isWorkDay(Date active_time_) {
        Calendar c = Calendar.getInstance();
        c.setTime(active_time_);
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek < 7 && dayOfWeek > 1;
    }

    public static void main(String[] args) throws Exception {
        String str = now().toString();
        System.out.println(str);
        System.out.println(datetime2Str(str2DateTime(str)));
        System.out.println(date2Str2(new Date()));
        System.out.println(getMonthHead(new Date()));
        System.out.println(getYearHead(new Date()));
        System.out.println(formatDate(new Date(), "yyyy-MM-00"));
        System.out.println(getWeekMonday(str2DateTime("2017-02-20")));

        System.out.println(isWorkDay(str2DateTime("2017-07-09")));
    }

}
